package com.ht.api.gaoxian;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;
import net.coobird.thumbnailator.Thumbnails;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class FileProcessor {
    /**
     * 文件规则结构体
     */
    public static class FileRule {
        private String type;           // 文件类型
        private Long maxSize;          // 最大大小
        private List<String> formats;  // 支持的格式
        private Integer maxLength;     // 最大边长（图片）
        private Integer maxShortSide;  // 最短边长（图片）
        private Integer maxDuration;   // 最大时长（视频）
        private Boolean allowFormatConversion; // 是否允许格式转换

        public FileRule(JSONObject rule) {
            this.type = rule.getStr("type", "").toLowerCase();

            // 所有字段都是可选的
            String sizeStr = rule.getStr("size");
            this.maxSize = sizeStr != null ? parseSize(sizeStr) : null;

            String formatsStr = rule.getStr("formats");
            this.formats = formatsStr != null ?
                    Arrays.asList(formatsStr.toLowerCase().split(",")) : null;

            this.maxLength = rule.getInt("maxLength", 0);
            this.maxShortSide = rule.getInt("maxShortSide", 0);
            this.maxDuration = rule.getInt("maxDuration", 0);
            this.allowFormatConversion = rule.getBool("allowFormatConversion", false);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("类型: ").append(type).append("\n");
            if (maxSize != null) sb.append("最大大小: ").append(formatSize(maxSize)).append("\n");
            if (formats != null) sb.append("支持格式: ").append(String.join(",", formats)).append("\n");
            if (maxLength > 0) sb.append("最大边长: ").append(maxLength).append("\n");
            if (maxShortSide > 0) sb.append("最短边长: ").append(maxShortSide).append("\n");
            if (maxDuration > 0) sb.append("最大时长: ").append(maxDuration).append("秒\n");
            return sb.toString();
        }
    }

    /**
     * 处理文件
     */
    public static File processFile(File file, JSONArray rules) throws Exception {
        if (file == null || !file.exists()) {
            throw new IllegalArgumentException("文件不存在");
        }

        // 获取文件类型
        String fileType = getFileType(file);

        // 查找匹配的规则
        FileRule matchedRule = findMatchingRule(fileType, rules);
        if (matchedRule == null) {
            System.out.println("未找到匹配的规则，文件类型: " + fileType);
            return file;
        }

        // 打印处理信息
        System.out.println("处理文件: " + file.getName());
        System.out.println("文件类型: " + fileType);
        System.out.println("应用规则: \n" + matchedRule);

        // 检查格式
        String currentFormat = getFileExtension(file);
        if (matchedRule.formats != null && !matchedRule.formats.isEmpty() &&
                !matchedRule.formats.contains(currentFormat)) {

            if (matchedRule.allowFormatConversion) {
                file = convertFormat(file, matchedRule);
            } else {
                throw new IllegalArgumentException("不支持的文件格式: " + currentFormat);
            }
        }

        // 根据类型处理文件
        switch (fileType) {
            case "image":
                return processImage(file, matchedRule);
            case "video":
                return processVideo(file, matchedRule);
            default:
                return processGeneralFile(file, matchedRule);
        }
    }

    /**
     * 处理图片
     */
    private static File processImage(File file, FileRule rule) throws IOException {
        BufferedImage image = ImageIO.read(file);
        if (image == null) {
            throw new IllegalArgumentException("无效的图片文件");
        }

        int width = image.getWidth();
        int height = image.getHeight();
        boolean needProcess = false;
        double scale = 1.0;

        // 检查长边和短边
        int longSide = Math.max(width, height);
        int shortSide = Math.min(width, height);

        if (rule.maxLength > 0 && longSide > rule.maxLength) {
            scale = Math.min(scale, (double) rule.maxLength / longSide);
            needProcess = true;
        }

        if (rule.maxShortSide > 0 && shortSide > rule.maxShortSide) {
            scale = Math.min(scale, (double) rule.maxShortSide / shortSide);
            needProcess = true;
        }

        // 检查文件大小
        if (rule.maxSize != null && file.length() > rule.maxSize) {
            needProcess = true;
        }

        if (!needProcess) {
            return file;
        }

        // 处理图片
        File outputFile = new File(file.getParent(), "processed_" + file.getName());
        double quality = 0.9;

        do {
            Thumbnails.of(file)
                    .scale(scale)
                    .outputQuality(quality)
                    .toFile(outputFile);

            quality -= 0.1;
        } while (rule.maxSize != null &&
                outputFile.length() > rule.maxSize &&
                quality > 0.1);

        System.out.println("处理后文件大小: " + formatSize(outputFile.length()));
        return outputFile;
    }

    /**
     * 处理视频
     */
    private static File processVideo(File file, FileRule rule) throws Exception {
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file);
        grabber.start();

        // 检查视频时长
        if (rule.maxDuration > 0) {
            int duration = (int) (grabber.getLengthInTime() / 1000000);
            if (duration > rule.maxDuration) {
                grabber.stop();
                throw new IllegalArgumentException("视频时长超过限制: " + duration + "秒");
            }
        }

        // 检查文件大小
        if (rule.maxSize == null || file.length() <= rule.maxSize) {
            grabber.stop();
            return file;
        }

        // 压缩视频
        File outputFile = new File(file.getParent(), "processed_" + file.getName());
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
                outputFile, grabber.getImageWidth(), grabber.getImageHeight()
        );

        recorder.setVideoCodec(28); // H.264
        recorder.setFormat("mp4");
        recorder.setVideoBitrate((int)(grabber.getVideoBitrate() * 0.8));
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.start();

        Frame frame;
        while ((frame = grabber.grab()) != null) {
            recorder.record(frame);
        }

        grabber.stop();
        recorder.stop();

        System.out.println("处理后文件大小: " + formatSize(outputFile.length()));
        return outputFile;
    }

    /**
     * 处理普通文件
     */
    private static File processGeneralFile(File file, FileRule rule) throws Exception {
        if (rule.maxSize != null && file.length() > rule.maxSize) {
            throw new IllegalArgumentException(
                    "文件大小超过限制: " + formatSize(file.length()) +
                            " > " + formatSize(rule.maxSize)
            );
        }
        return file;
    }

    /**
     * 格式转换
     */
    private static File convertFormat(File file, FileRule rule) throws Exception {
        String currentFormat = getFileExtension(file);
        String targetFormat = rule.formats.get(0); // 使用第一个支持的格式

        if (isImage(file)) {
            return convertImageFormat(file, targetFormat);
        } else if (isVideo(file)) {
            return convertVideoFormat(file, targetFormat);
        }

        throw new IllegalArgumentException("不支持的文件格式转换: " + currentFormat);
    }

    /**
     * 转换图片格式
     */
    private static File convertImageFormat(File file, String targetFormat) throws IOException {
        BufferedImage image = ImageIO.read(file);
        File outputFile = new File(file.getParent(),
                file.getName().substring(0, file.getName().lastIndexOf(".")) +
                        "." + targetFormat);
        ImageIO.write(image, targetFormat, outputFile);
        return outputFile;
    }

    /**
     * 转换视频格式
     */
    private static File convertVideoFormat(File file, String targetFormat) throws Exception {
        File outputFile = new File(file.getParent(),
                file.getName().substring(0, file.getName().lastIndexOf(".")) +
                        "." + targetFormat);

        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(file);
        grabber.start();

        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
                outputFile,
                grabber.getImageWidth(),
                grabber.getImageHeight()
        );

        recorder.setFormat(targetFormat);
        recorder.setVideoCodec(28); // H.264
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.start();

        Frame frame;
        while ((frame = grabber.grab()) != null) {
            recorder.record(frame);
        }

        grabber.stop();
        recorder.stop();
        return outputFile;
    }

    /**
     * 查找匹配的规则
     */
    private static FileRule findMatchingRule(String fileType, JSONArray rules) {
        if (rules == null) return null;

        for (int i = 0; i < rules.size(); i++) {
            JSONObject rule = rules.getJSONObject(i);
            if (fileType.equals(rule.getStr("type", "").toLowerCase())) {
                return new FileRule(rule);
            }
        }
        return null;
    }

    /**
     * 获取文件类型
     */
    private static String getFileType(File file) {
        String extension = getFileExtension(file);
        if (isImage(file)) {
            return "image";
        } else if (isVideo(file)) {
            return "video";
        } else {
            return "file";
        }
    }

    /**
     * 判断是否为图片
     */
    private static boolean isImage(File file) {
        String extension = getFileExtension(file);
        return Arrays.asList("jpg", "jpeg", "png").contains(extension);
    }

    /**
     * 判断是否为视频
     */
    private static boolean isVideo(File file) {
        String extension = getFileExtension(file);
        return "mp4".equals(extension);
    }

    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(File file) {
        String name = file.getName();
        int lastIndexOf = name.lastIndexOf(".");
        if (lastIndexOf == -1) {
            return "";
        }
        return name.substring(lastIndexOf + 1).toLowerCase();
    }

    /**
     * 解析文件大小字符串
     */
    private static long parseSize(String sizeStr) {
        if (sizeStr == null || sizeStr.trim().isEmpty()) {
            return 0L;
        }

        sizeStr = sizeStr.toUpperCase();
        long multiplier = 1;

        if (sizeStr.endsWith("KB")) {
            multiplier = 1024L;
        } else if (sizeStr.endsWith("MB")) {
            multiplier = 1024L * 1024L;
        } else if (sizeStr.endsWith("GB")) {
            multiplier = 1024L * 1024L * 1024L;
        }

        String number = sizeStr.replaceAll("[^0-9.]", "");
        return (long) (Double.parseDouble(number) * multiplier);
    }

    /**
     * 格式化文件大小
     */
    private static String formatSize(long size) {
        if (size < 1024) {
            return size + " bytes";
        } else if (size < 1024 * 1024) {
            return String.format("%.2f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", size / (1024.0 * 1024));
        } else {
            return String.format("%.2f GB", size / (1024.0 * 1024 * 1024));
        }
    }
}